package game.ouroboros.enemy;

import java.util.Random;
import framework.DynamicGameObject;
import framework.maths.Vector2;
import game.ouroboros.Projectile;
import game.ouroboros.magic.World;
import game.ouroboros.traps.Portao;
import game.ouroboros.traps.Trap;
import java.util.List;
import java.util.ArrayList;

import android.util.Log;

public abstract class Enemy extends DynamicGameObject {
	
	// constantes de tipo
	public static final int FIRE = 0; // burn
	public static final int WATHER = 1; // def down
	public static final int THUNDER = 2; // stun
	public static final int EARTH = 3; // stun
	public static final int WIND = 4; // slow
	public static final int NORMAL = 5;
	
	// estados
	public static final int BURNED = 0;
	public static final int STUNED = 1;
	public static final int SLOWED = 2;
	public static final int DEF_DAWNED = 3;
	public static final int ATK_DAWNED = 4;
	public static final int RUNNING = 5;
	public static final int ATACKING = 6;
	
	Random rand = new Random(System.currentTimeMillis());
	public static List<Enemy> list = new ArrayList<Enemy>();
	Portao portao = Portao.getPortao(16, 16, 50, 50);
	
	public boolean boss = false;
	public int type; // tipo do inimigo
	public int maxDamAtk;
	public int damAtk; // dano causado pelo ataque
	public int maxDamDef;
	public int damDef; // dano de ataque minimo para tirar vida, seria como uma blindagem
	public int maxLife; //limite maximo de vida
	public int life; // vida do personagem
	public int size; // tamanho do personagem
	public int maxVel = 32;
	public int vel = 32;
	public boolean alive = true;
	private Vector2 destino;
	private int rotapos = 1;
	private int rota;
	public int state;
	private int stateTime;
	
	public Enemy(float x, float y, float width, float height){
        super(x, y, width, height);
        this.alive = true;
        rota = rand.nextInt(3);
        Enemy.list.add(this);
		}
	
	// metodos
	
	public static boolean isFree(float x,float y){
		for(Enemy e : Enemy.list){
			if(e.position.x == x && e.position.y == y)
				return true;
		}
		return false;
	}
	
	public void regenLife(int val){
		if(this.life+val<=this.maxLife){
			this.life += val;
		}else{
			this.life = this.maxLife;
		}
	}
	
	public void die(){
		if(this.life==0){
			this.alive = false;
			Enemy.list.remove(this);
		}
	}
	
	public boolean isAlive(){
		return this.alive;
	}
	
	public void damageStateManager(int type){
		if(this.type!=type){
			switch(type){
			case FIRE: this.state = BURNED; this.stateTime = 0; break;
			case WATHER: this.state = DEF_DAWNED; this.stateTime = 0; break;
			case WIND: this.state = SLOWED; this.stateTime = 0; break;
			case EARTH: this.state = ATK_DAWNED; this.stateTime = 0; break;
			case THUNDER: this.state = STUNED; this.stateTime = 0; break;
			case NORMAL: break;
			default: break;
			}
		}
		if(this.life<=0) this.die();
	}
	
	public void receiveDamage(int valor,int type){
		if(this.type!=type&&type!=NORMAL&&valor>=this.damDef){
			this.life-=valor*2;
		}
		if(this.type==type||type==NORMAL){
			this.life-=valor;
		}
		this.damageStateManager(type);
	}
		
	public void receiveDamage(Projectile proj){
		int valor = proj.getDamage();
		int type = proj.getType();
		if(this.type!=type&&type!=NORMAL&&valor>=this.damDef){
			this.life-=valor*2;
		}
		if(this.type==type||type==NORMAL){
			this.life-=valor;
		}
		this.damageStateManager(type);
	}
	
	public void atackPortao(){
		portao.attackedBy(this);
	}
	
	public void collidedWith(Projectile p){
		this.receiveDamage(p.damage, p.type);
	}
	
	public void collidedWith(Trap t){
		if (!(t instanceof Portao))
			this.receiveDamage(t.damAtk, t.type);
	}
	
	private void checkState(){
		if(this.position.x==16||this.position.y==16){
			this.state = ATACKING;
		}
		if(this.stateTime==5){
			this.state = RUNNING;
			this.damAtk = this.maxDamAtk;
			this.damDef = this.maxDamDef;
			this.vel = this.maxVel;
			this.stateTime = 0;
		}
		switch(state){
		case BURNED: this.receiveDamage(15, FIRE); this.stateTime++; break;
		case SLOWED: this.vel = (int)(this.vel*0.8); this.stateTime++; break;
		case DEF_DAWNED: this.damDef = 0; this.stateTime++; break;
		case ATK_DAWNED: this.damAtk = (int)(this.damAtk/2); this.stateTime++; break;
		case STUNED: this.vel = 0; this.stateTime++; break;
		case ATACKING: this.atackPortao(); break;
		default: break;
		}
	}
	
	public void update(float deltaTime){
		checkState();
		if(this.alive){
			move();
		}
	}

	public void move(){
		switch(rota){
		case 0:
			this.destino = new Vector2(World.rota0.get(this.rotapos));
			break;
		case 1:
			this.destino = new Vector2(World.rota1.get(this.rotapos));
			break;
		case 2: break;
		default: break;
		}
		try{
		for(int i=0;i<vel;i++){
			if(this.position.x!=destino.x||this.position.y!=destino.y){
				if(this.position.x>this.destino.x&&Enemy.isFree(this.position.x-1,this.position.x)){
					this.position.x--;
				}
				if(this.position.y>this.destino.y&&Enemy.isFree(this.position.y-1,this.position.y)){
					this.position.y--;
				}
				if(this.position.x<this.destino.x&&Enemy.isFree(this.position.x+1,this.position.x)){
					this.position.x++;
				}
				if(this.position.y>this.destino.y&&Enemy.isFree(this.position.y+1,this.position.y)){
					this.position.y++ ;
				}
			}else{
				if(this.position.x!=16||this.position.y!=16){
					rotapos++;
				}
			}
		}
		}catch (Exception e) {
			Log.v("<TAG>","The god's have abadom me");
		}
	}

	public void reset(float x, float y) {
		this.position.x = x;
		this.position.y = y;
		this.life = 10;
		this.alive = true;
	}
}